﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hydra.Shell;

namespace Hydra.Shell.Attributes
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public class ProvideEditorExtensionAttribute : RegistrationAttribute
    {
        private bool editorFactoryNotify;
        private string editorName;
        private string extension;
        private System.Guid factory;
        private int priority;
        private System.Guid project;
        private int resId;
        private string templateDir;

        public ProvideEditorExtensionAttribute(object factoryType, string extension, int priority)
        {
            if (!extension.StartsWith(".", System.StringComparison.OrdinalIgnoreCase))
            {
                throw new System.ArgumentException(string.Format("Extension Needs Dot", new object[] { extension }));
            }

            if (factoryType is string)
            {
                this.factory = new System.Guid((string)((string)factoryType));
            }
            else if (factoryType is System.Type)
            {
                this.factory = ((System.Type)factoryType).GetGuid();
            }
            else
            {
                if (!(factoryType is System.Guid))
                {
                    throw new System.ArgumentException(string.Format("Invalid Factory Type", new object[] { factoryType }));
                }
            
                this.factory = (System.Guid)factoryType;
            }

            this.extension = extension;
            this.priority = priority;
            this.project = System.Guid.Empty;
            this.templateDir = "";
            this.resId = 0;
            this.editorFactoryNotify = false;
        }

        private string ProjectRegKeyName(RegistrationAttribute.RegistrationContext context)
        {
            return string.Format(System.Globalization.CultureInfo.InvariantCulture, @"Projects\{0}\AddItemTemplates\TemplateDirs\{1}", new object[] { this.project.ToString("B"), context.ComponentType.GUID.ToString("B") });
        }

        public override void Register(RegistrationAttribute.RegistrationContext context)
        {
            context.Log.WriteLine(string.Format("Reg_NotifyEditorExtension", new object[] { this.Extension, this.Factory.ToString("B") }));

            using (RegistrationAttribute.Key key = context.CreateKey(this.RegKeyName))
            {
                if (!string.IsNullOrEmpty(this.DefaultName))
                {
                    key.SetValue((string)null, this.DefaultName);
                }

                if (this.resId != 0)
                {
                    key.SetValue("DisplayName", "#" + ((int)this.resId).ToString(System.Globalization.CultureInfo.InvariantCulture));
                }

                key.SetValue("Package", context.ComponentType.GUID.ToString("B"));
            }

            using (RegistrationAttribute.Key key2 = context.CreateKey(this.RegKeyName + @"\Extensions"))
            {
                key2.SetValue(this.Extension.Substring(1), (int)this.Priority);
            }

            if (this.project != System.Guid.Empty)
            {
                string str = this.ProjectRegKeyName(context) + @"\/1";

                using (RegistrationAttribute.Key key3 = context.CreateKey(str))
                {
                    if (this.resId != 0)
                    {
                        key3.SetValue("", "#" + ((int)this.resId).ToString(System.Globalization.CultureInfo.InvariantCulture));
                    }

                    if (this.templateDir.Length != 0)
                    {
                        Uri uri = new Uri(context.ComponentType.Assembly.CodeBase);
                        string str2 = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(uri.LocalPath), this.templateDir);
                        str2 = context.EscapePath(System.IO.Path.GetFullPath(str2));
                        key3.SetValue("TemplatesDir", str2);
                    }

                    key3.SetValue("SortPriority", (int)this.Priority);
                }
            }

            if (this.EditorFactoryNotify)
            {
                if (this.project == System.Guid.Empty)
                {
                    throw new System.ArgumentException("No Project For Editor Factory Notify");
                }

                using (RegistrationAttribute.Key key4 = context.CreateKey(this.EditorFactoryNotifyKey))
                {
                    key4.SetValue("EditorFactoryNotify", this.Factory.ToString("B"));
                }
            }
        }

        public override void Unregister(RegistrationAttribute.RegistrationContext context)
        {
            context.RemoveKey(this.RegKeyName);

            if (this.project != System.Guid.Empty)
            {
                context.RemoveKey(this.ProjectRegKeyName(context));

                if (this.EditorFactoryNotify)
                {
                    context.RemoveKey(this.EditorFactoryNotifyKey);
                }
            }
        }

        public string DefaultName
        {
            get
            {
                return this.editorName;
            }

            set
            {
                this.editorName = value;
            }
        }

        public bool EditorFactoryNotify
        {
            get
            {
                return this.editorFactoryNotify;
            }

            set
            {
                this.editorFactoryNotify = value;
            }
        }

        private string EditorFactoryNotifyKey
        {
            get
            {
                return string.Format(System.Globalization.CultureInfo.InvariantCulture, @"Projects\{0}\FileExtensions\{1}", new object[] { this.project.ToString("B"), this.Extension });
            }
        }

        public string Extension
        {
            get
            {
                return this.extension;
            }
        }

        public Guid Factory
        {
            get
            {
                return this.factory;
            }
        }

        public int NameResourceID
        {
            get
            {
                return this.resId;
            }
            
            set
            {
                this.resId = value;
            }
        }

        public int Priority
        {
            get
            {
                return this.priority;
            }
        }

        public string ProjectGuid
        {
            get
            {
                return this.project.ToString();
            }

            set
            {
                this.project = new System.Guid(value);
            }
        }

        private string RegKeyName
        {
            get
            {
                return string.Format(System.Globalization.CultureInfo.InvariantCulture, @"Editors\{0}", new object[] { this.Factory.ToString("B") });
            }
        }

        public string TemplateDir
        {
            get
            {
                return this.templateDir;
            }

            set
            {
                this.templateDir = value;
            }
        }
    }
}
